package com.tange.ai.iot.client.gnssa.newui;

import android.app.Activity;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.os.CountDownTimer;
import android.os.Handler;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.core.util.Consumer;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.GsonUtils;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleMtuChangedCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.gyf.immersionbar.ImmersionBar;
import com.tange.ai.iot.client.gnssa.R;
import com.tange.ai.iot.client.gnssa.bean.BleSLDevice;
import com.tange.ai.iot.client.gnssa.bean.LoginBean;
import com.tange.ai.iot.client.gnssa.bean.RespMsg;
import com.tange.ai.iot.client.gnssa.home.HomeActivity;
import com.tange.ai.iot.client.gnssa.httpservice.DeviceService;
import com.tange.ai.iot.client.gnssa.utils.HexUtil;
import com.tange.ai.iot.client.gnssa.utils.ble.BleConfig;
import com.tange.core.data.structure.Ret;
import com.tange.feature.binding.query.DeviceBindingDirectly;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;

import base.activity.BaseActivity;
import base.http.rxandroid.CustomDisposableForJava;
import base.http.utils.RetrofitManager;
import base.utils.LogUtil;
import io.reactivex.android.schedulers.AndroidSchedulers;

public class WiFiConfigActivity extends BaseActivity {

    private TextView tvBack;
    private TextView tvTitle;
    private TextView tvRight;
    private ConstraintLayout clTitlebar;
    private LinearLayout llConnectWifi;
    private RecyclerView rvSuccess;
    private LinearLayout llConnectSuccess;
    private RecyclerView rvFail;
    private LinearLayout llConnectFail;
    private LinearLayout llConnectResult;
    private LinearLayout container;


    private ArrayList<BleSLDevice> selectBleList;
    private String configeData;
    private boolean isSendWifiInfoSuccess = false;
    private CountDownTimer allTimeOut;
    private BaseQuickAdapter<BleSLDevice, BaseViewHolder> mSuccessAdapter;
    private BaseQuickAdapter<BleSLDevice, BaseViewHolder> mFailAdapter;
    private TextView tvFinish;
    DeviceService deviceService = new RetrofitManager().getDefaultClient(DeviceService.class);

    @Override
    protected int getLayoutId() {
        return R.layout.activity_wifi_config;
    }

    @Override
    protected void initData() {
        ImmersionBar.with(this).fitsSystemWindows(true).statusBarDarkFont(true).init();
        setTitle("连接Wi-Fi");

        tvBack = findViewById(R.id.tv_back);
        tvTitle = findViewById(R.id.tv_title);
        tvRight = findViewById(R.id.tv_right);
        clTitlebar = findViewById(R.id.cl_titlebar);
        llConnectWifi = findViewById(R.id.ll_connect_wifi);
        rvSuccess = findViewById(R.id.rv_success);
        llConnectSuccess = findViewById(R.id.ll_connect_success);
        rvFail = findViewById(R.id.rv_fail);
        llConnectFail = findViewById(R.id.ll_connect_fail);
        llConnectResult = findViewById(R.id.ll_connect_result);
        container = findViewById(R.id.container);

        configeData = getIntent().getStringExtra("configeData");
        mSuccessAdapter = new BaseQuickAdapter<BleSLDevice, BaseViewHolder>(R.layout.item_scan_ble) {
            @Override
            protected void convert(@NonNull BaseViewHolder holder, BleSLDevice item) {
                holder.itemView.findViewById(R.id.cb).setVisibility(View.GONE);
                holder.setText(
                        R.id.tv_device_name,
                        "BleName:" + item.bleDevice.getName() + "\nuuid:" + item.tangeUUID + "\nMac:" + item.wifiMac + "\nPID:" + item.pId
                );
            }
        };
        LinearLayoutManager successLayoutManager = new LinearLayoutManager(mContext);
        rvSuccess.setLayoutManager(successLayoutManager);
        rvSuccess.setAdapter(mSuccessAdapter);

        mFailAdapter = new BaseQuickAdapter<BleSLDevice, BaseViewHolder>(R.layout.item_scan_ble) {
            @Override
            protected void convert(@NonNull BaseViewHolder holder, BleSLDevice item) {
                holder.itemView.findViewById(R.id.cb).setVisibility(View.GONE);
                holder.setText(
                        R.id.tv_device_name,
                        "BleName:" + item.bleDevice.getName() + "\nuuid:" + item.tangeUUID + "\nMac:" + item.wifiMac + "\nPID:" + item.pId
                );
            }
        };
        LinearLayoutManager failLayoutManager = new LinearLayoutManager(mContext);
        rvFail.setLayoutManager(failLayoutManager);
        rvFail.setAdapter(mFailAdapter);

        allTimeOut = new CountDownTimer(30 * 1000, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
            }

            @Override
            public void onFinish() {
                checkAllBleConfigState(true);
            }
        };
        startBleConfig();

        tvFinish = findViewById(R.id.tv_finish);
        tvFinish.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ActivityUtils.finishActivity(HomeActivity.class);
                readyGo(HomeActivity.class);
                finish();
            }
        });
    }

    private void startBleConfig() {
        if (selectBleList != null && selectBleList.size() > 0) {
            for (BleSLDevice bleSLDevice : selectBleList) {
                startConnect(bleSLDevice.bleDevice.getMac(), bleSLDevice);
            }
        }
    }


    private void startConnect(String bleMac, BleSLDevice bleSLDevice) {
        boolean connected = BleManager.getInstance().isConnected(bleMac);
        if (connected) {
            LogUtil.INSTANCE.e("蓝牙本来连接了，没做逻辑处理");
        } else {

            BleManager.getInstance().connect(bleMac, new BleGattCallback() {
                @Override
                public void onStartConnect() {
                    LogUtil.INSTANCE.e("开始蓝牙连接");
                    bleSLDevice.status = 0;
                }

                @Override
                public void onConnectFail(BleDevice bleDevice, BleException exception) {
                    LogUtil.INSTANCE.e("蓝牙连接失败");
                    bleSLDevice.status = 1;
                }

                @Override
                public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                    bleSLDevice.status = 2;
                    bleConnectSuccess(bleDevice, gatt, bleSLDevice);
                }

                @Override
                public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
                    LogUtil.INSTANCE.e("======== 蓝牙断开连接 ==========");
                }
            });
        }
    }

    private void bleConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, BleSLDevice bleSLDevice) {
        LogUtil.INSTANCE.e("成功连接蓝牙");
        LogUtil.INSTANCE.e("======== 成功连接蓝牙MAC:+" + bleDevice.getMac() + " ==========");
        BluetoothGattService veeLinkService = null;
        for (BluetoothGattService service : gatt.getServices()) {
            if (BleConfig.SERVICE_UUID.equals(service.getUuid())) {
                veeLinkService = service;
            }
        }
        if (veeLinkService == null) {
            LogUtil.INSTANCE.e("没有获取到SERVICE_UUID，蓝牙主动断开连接");
            BleManager.getInstance().disconnect(bleDevice);
            bleSLDevice.status = 3;
            return;
        }

        BluetoothGattCharacteristic veeLinkWriteCharacteristic = null;
        for (BluetoothGattCharacteristic characteristic : veeLinkService.getCharacteristics()) {
            boolean read = (characteristic.getProperties() | BluetoothGattCharacteristic.PROPERTY_READ) > 0;
            boolean write = (characteristic.getProperties() | BluetoothGattCharacteristic.PROPERTY_WRITE) > 0;
            boolean notify = (characteristic.getProperties() | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0;
            LogUtil.INSTANCE.e("UUID-char:" + characteristic.getUuid().toString() + " 读：" + read + " 写：" + write + " 通知：" + notify);
            if (BleConfig.CHARACTERISTIC_WRITE_UUID.equals(characteristic.getUuid())) {
                veeLinkWriteCharacteristic = characteristic;
            }
        }
        if (veeLinkWriteCharacteristic == null) {
            BleManager.getInstance().disconnect(bleDevice);
            LogUtil.INSTANCE.e("没有获取到特征值，蓝牙主动断开连接");
            bleSLDevice.status = 3;
            return;
        }

        //设置发送数据包的延迟
        BleManager.getInstance().requestConnectionPriority(bleDevice, BluetoothGatt.CONNECTION_PRIORITY_HIGH);

        CountDownTimer sendWifiInfoTimer = new CountDownTimer(1 * 1000, 1 * 1000) {
            @Override
            public void onTick(long millisUntilFinished) {
                sendWiFiInfo(bleDevice);
            }

            @Override
            public void onFinish() {
                if (!isSendWifiInfoSuccess) {
                    LogUtil.INSTANCE.e("============== 发送 蓝牙配网信息  超时+失败==============" + bleDevice.getMac());
                }
            }
        };


        //订阅读
        BleManager.getInstance().notify(bleDevice, BleConfig.SERVICE_UUID_STR, BleConfig.CHARACTERISTIC_NOTIFY_UUID_STR, new BleNotifyCallback() {
            @Override
            public void onNotifySuccess() {
                LogUtil.INSTANCE.e("=============== 订阅成功 ====================");
            }

            @Override
            public void onNotifyFailure(BleException exception) {
                LogUtil.INSTANCE.e("================ 订阅失败 ==================");
            }

            @Override
            public void onCharacteristicChanged(byte[] data) {
                LogUtil.INSTANCE.e("收到Ble数据：" + HexUtil.bytesToHexString(data));
                if (Byte.toUnsignedInt(data[1]) == 0xFF) {
                    isSendWifiInfoSuccess = true;
                    int length = data[0] - 1;
                    byte[] bytes = new byte[length];
                    System.arraycopy(data, 2, bytes, 0, bytes.length);
                    String str = HexUtil.bytesToHexString(bytes);
                    int result = Integer.parseInt(str, 16);
                    if (result == 0xFF) {
                        goBindDevice(bleSLDevice);
                    } else if (result == 0xF1) {

                    } else {
                        bleSLDevice.status = 3;
                    }
                    checkAllBleConfigState(false);
                }
            }
        });

        BleManager.getInstance().setMtu(bleSLDevice.bleDevice, 200, new BleMtuChangedCallback() {
            @Override
            public void onSetMTUFailure(BleException exception) {
                LogUtil.INSTANCE.e("设置MTU失败啦！！！！！！");
                sendWifiInfoTimer.start();
            }

            @Override
            public void onMtuChanged(int mtu) {
                LogUtil.INSTANCE.e("设置MTU成功，为：" + mtu);
                sendWifiInfoTimer.start();
            }
        });
    }

    private void goBindDevice(BleSLDevice bleSLDevice) {
//        DeviceBindingDirectly.require(bleSLDevice.tangeUUID, bleSLDevice.bleDevice.getName(), new Consumer<Ret>() {
//            @Override
//            public void accept(Ret ret) {
//                LogUtil.INSTANCE.e("绑定结果："+ GsonUtils.toJson(ret)+"  绑定的id是:"+bleSLDevice.tangeUUID);
//                if(ret.getSuccess()){
//                    bleSLDevice.status=4;
//                }else{
//                    bleSLDevice.status=3;
//                }
//                checkAllBleConfigState(false);
//            }
//        });

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                DeviceBindingDirectly.requireEx(bleSLDevice.tangeUUID, DeviceBindingDirectly.BindingMode.MODE_DEVICE, false, false, bleSLDevice.bleDevice.getName(), new Consumer<Ret>() {
                    @Override
                    public void accept(Ret ret) {
                        LogUtil.INSTANCE.e("绑定结果：" + GsonUtils.toJson(ret) + "  绑定的id是:" + bleSLDevice.tangeUUID);
                        if (ret.getSuccess()) {
                            bleSLDevice.status = 4;
                            bindDeviceMyCloud(bleSLDevice.tangeUUID, bleSLDevice.bleDevice.getMac());
                        } else {
                            bleSLDevice.status = 3;
                        }
                        checkAllBleConfigState(false);
                    }
                });
            }
        }, 5000);
    }

    private void bindDeviceMyCloud(String tangeUUID, String mac) {
        HashMap<String, Object> params = new HashMap<>();
        params.put("deviceName", tangeUUID);
        params.put("mac", mac);

        deviceService.postBindDevice(params)
                .subscribeOn(AndroidSchedulers.mainThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new CustomDisposableForJava<RespMsg<Object>>(mContext) {
                    @Override
                    public void onNext(RespMsg<Object> bean) {
                        try {
                            LogUtil.INSTANCE.e("http:" + GsonUtils.toJson(bean));
                        } catch (Exception e) {
                        }
                    }

                    @Override
                    public void onError(Throwable e) {
                        LogUtil.INSTANCE.e(e + "");
                    }
                });
    }

    private void sendWiFiInfo(BleDevice bleDevice) {
        LogUtil.INSTANCE.e("============== 开始发送 蓝牙配网信息==============" + bleDevice.getMac());
        //==========开始发送配网信息================

        String ssid = getIntent().getStringExtra("ssid");
        String pwd = getIntent().getStringExtra("pwd");

        byte[] ssidBytes = ssid.getBytes();
        byte[] pwdBytes = pwd.getBytes();


        byte[] wifiBytes = new byte[1 + 1 + ssidBytes.length + 1 + 1 + pwdBytes.length];

        wifiBytes[0] = (byte) (1 + ssidBytes.length);
        wifiBytes[1] = 0x01;
        System.arraycopy(ssidBytes, 0, wifiBytes, 2, ssidBytes.length);

        wifiBytes[2 + ssidBytes.length] = (byte) (1 + pwdBytes.length);
        wifiBytes[3 + ssidBytes.length] = 0x02;
        System.arraycopy(pwdBytes, 0, wifiBytes, 4 + ssidBytes.length, pwdBytes.length);

        sendBleData(bleDevice, HexUtil.bytesToHexString(wifiBytes), 0, 3);
    }


    private void sendBleData(BleDevice bleDevice, String hexString, final int cur, int count) {
        BleManager.getInstance().write(bleDevice
                , BleConfig.SERVICE_UUID_STR
                , BleConfig.CHARACTERISTIC_WRITE_UUID_STR
                , HexUtil.hexStringToBytes(hexString.toUpperCase())
                , false//不自动分割
                , new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(int current, int total, byte[] justWrite) {
                        LogUtil.INSTANCE.e("write success, current: " + current
                                + " total: " + total
                                + " justWrite: " + HexUtil.bytesToHexString(justWrite));
                    }

                    @Override
                    public void onWriteFailure(BleException exception) {
                        LogUtil.INSTANCE.e(exception.toString());
                        if (!BleManager.getInstance().isConnected(bleDevice)) {
                            return;
                        }
                        int nowCur = cur;
                        if (nowCur < count) {
                            new CountDownTimer(1000, 1000) {
                                @Override
                                public void onTick(long millisUntilFinished) {
                                }

                                @Override
                                public void onFinish() {
                                    int nowCur = cur;
                                    nowCur++;
                                    sendBleData(bleDevice, hexString, nowCur, count);
                                }
                            };
                        }
                    }
                });
    }

    private void sendBleDataList(BleDevice bleDevice, LinkedList<byte[]> linkedList, final int cur, int count) {
        if (linkedList.size() == 0) return;
        BleManager.getInstance().write(bleDevice
                , BleConfig.SERVICE_UUID_STR
                , BleConfig.CHARACTERISTIC_WRITE_UUID_STR
                , linkedList.get(0)
                , false//不自动分割
                , new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(int current, int total, byte[] justWrite) {
                        LogUtil.INSTANCE.e("write success, current: " + current
                                + " total: " + total
                                + " justWrite: " + HexUtil.bytesToHexString(justWrite));
                        if (linkedList.size() > 0) {
                            linkedList.remove(0);
                            if (linkedList.size() > 0) {
                                sendBleDataList(bleDevice, linkedList, 0, count);
                            }
                        }

                    }

                    @Override
                    public void onWriteFailure(BleException exception) {
                        LogUtil.INSTANCE.e(exception.toString());
                        if (!BleManager.getInstance().isConnected(bleDevice)) {
                            return;
                        }
                        int nowCur = cur;
                        if (nowCur < count) {
                            new CountDownTimer(1000, 1000) {
                                @Override
                                public void onTick(long millisUntilFinished) {
                                }

                                @Override
                                public void onFinish() {
                                    int nowCur = cur;
                                    nowCur++;
                                    sendBleDataList(bleDevice, linkedList, nowCur, count);
                                }
                            };
                        }
                    }
                });
    }

    private void checkAllBleConfigState(boolean isAllTimeOut) {
        //-1 初始化 0 蓝牙连接 1连接失败 2连接成功 3配网失败 4配网成功
        if (selectBleList != null) {
            int count = 0;

            ArrayList<BleSLDevice> successList = new ArrayList<>();
            ArrayList<BleSLDevice> failList = new ArrayList<>();
            for (BleSLDevice device : selectBleList) {
                if (device.status == 1 || device.status == 3 || device.status == 4) {
                    count++;
                    if (device.status == 1 || device.status == 3) {
                        failList.add(device);
                    } else {
                        successList.add(device);
                    }
                }
            }
            if (count >= selectBleList.size() || isAllTimeOut) {
                llConnectWifi.setVisibility(View.GONE);
                llConnectResult.setVisibility(View.VISIBLE);
                mSuccessAdapter.setNewInstance(successList);
                mFailAdapter.setNewInstance(failList);
            }
        } else {
            showShortToast("没有选中可配网的蓝牙设备");
            readyGo(HomeActivity.class);
            finish();
        }
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        allTimeOut.cancel();
        BleManager.getInstance().disconnectAllDevice();
    }

    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onBleDataGet(EventBusEntity entity) {
        try {
            if (entity.tag.equals("BLE")) {
                selectBleList = (ArrayList<BleSLDevice>) entity.data;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
